using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using Lean.Touch;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 主城游戏控制器
    /// 用于执行玩家移动，交互等逻辑
    /// </summary>
    public class MainCityGamepadCtrl : MainCityControllerBase
    {
        public event Action<LeanFinger> onTouchTap;
        public event Action<List<LeanFinger>> onTouchGesture;
        public event Action<LeanFinger> onTouchUp;

        /// <summary>
        /// 交互ui，摇杆和按钮
        /// </summary>
        private UILevelInput uiInput => regionCtrl?.uiInput;
        /// <summary>
        /// 是否正在移动中
        /// </summary>
        public bool isMoving { private set; get; }
        /// <summary>
        /// 交互控制器是否激活
        /// 注意这个接口只能由自身的生命周期函数（如Dispose）和外部生命周期函数或管理函数调用set（如OnSceneLoaded）
        /// 其他的交互锁定控制请参考isLock
        /// </summary>
        public bool isActive { get; set; }
        /// <summary>
        /// 交互是否被锁定（根据各种锁定交互的操作进行计算）
        /// </summary>
        public bool isLock => !isActive && _isInteractingWithNpc;
        /// <summary>
        /// 是否正在和npc交互
        /// </summary>
        private bool _isInteractingWithNpc;
        /// <summary>
        /// 计算当前交互对象频率的计时器
        /// </summary>
        private float _checkInteractObjTimer;
        /// <summary>
        /// 玩家化身
        /// </summary>
        private MainCityPlayerAvatarEntity _playerAvatarEntity;
        private int _curInteracType;
        private int _curInteractEntityId;
        private uint _playInteractAnimTimerId;
        private float _syncMoveElapsedTime;
        private float _moveCheckElapsedTime;

        private MainCityPlayerAvatarEntity playerAvatarEntity
        {
            get
            {
                _playerAvatarEntity ??= regionCtrl.entityCtrl.playerAvatarEntity;
                return _playerAvatarEntity;
            }
        }

        /// <summary>
        /// 交互头顶指示条
        /// </summary>
        public PositionConstraint headIndicator { protected set; get; }
        public MainCityNormalEntity indicateEntity { get; private set; }

        protected override void OnModuleGameplayInit()
        {
            isActive = false;
            //初始化lean touch
            LeanTouch.OnGesture += OnTouchGesture;
            LeanTouch.OnFingerTap += OnTouchTap;
            LeanTouch.OnFingerUp += OnTouchUp;
        }

        protected override void OnSceneLoaded()
        {
            // 头顶指示器
            headIndicator = GameObject.Instantiate(mainCityCtrl.permanentResource.prefabHeadIndicator).AddComponent<PositionConstraint>();
            // 高度偏移
            headIndicator.AddSource(new ConstraintSource() { weight = 1 });
            headIndicator.constraintActive = true;
            SetHeadIndicatorOn(false);
        }

        public void AddJoystickListener()
        {
            if (uiInput != null)
            {
                uiInput.Show();
                uiInput.AddJoystickListener(OnJoystickMove, OnJoystickUp);
                uiInput.onClickInteract += OnClickInteract;
            }
        }

        private void OnTouchGesture(List<LeanFinger> fingers)
        {
            if (!isActive)
            {
                return;
            }
            onTouchGesture?.Invoke(fingers);
        }

        private void OnTouchTap(LeanFinger leanFinger)
        {
            if (!isActive)
            {
                return;
            }
            onTouchTap?.Invoke(leanFinger);
        }

        private void OnTouchUp(LeanFinger leanFinger)
        {
            if (!isActive)
            {
                return;
            }
            onTouchUp?.Invoke(leanFinger);
        }

        public void OnJoystickMove(JoystickData joystickData)
        {
            if (!isActive)
            {
                return;
            }

            playerAvatarEntity.MoveStep(joystickData.angle, joystickData.power);
            var animCom = playerAvatarEntity.GetComponent<MainCityAnimationComponent>(ETComponentType.EntityAnimation);
            animCom.SetJoyStickPower(joystickData.power);

            bool isStartMove = false;
            if (!isMoving)
            {
                isStartMove = true;
                MsgDispatcher.Broadcast(MsgEventType.EntityStartMove, joystickData.power);
            }
            animCom.SetStartMove(isStartMove);
            isMoving = true;
        }

        public void OnJoystickUp()
        {
            if (!isActive)
            {
                return;
            }
            var animCom = playerAvatarEntity.GetComponent<MainCityAnimationComponent>(ETComponentType.EntityAnimation);
            animCom.SetJoyStickPower(0);
            StopCharacterMove();
        }

        private void StopCharacterMove(bool isImmediately = false)
        {
            var character = playerAvatarEntity;
            if (character != null)
            {
                character.StopMove(isImmediately);
            }

            isMoving = false;
        }

        public void OnClickInteract()
        {
            if (isLock)
            {
                return;
            }
            ClickInteractLogic().Forget();
        }

        /// <summary>
        /// 点击交互按钮的逻辑
        /// </summary>
        /// <returns></returns>
        private async UniTaskVoid ClickInteractLogic()
        {
            _isInteractingWithNpc = true;
            StopCharacterMove();
            //播放交互动作
            await PlayInteractAnimation();
            if (_curInteracType != 0)
            {
                var interactCfg = TableCenter.entityInteractType.Get(_curInteracType);
                if (regionCtrl.entityCtrl.entities.TryGetValue(_curInteractEntityId, out var otherEntity)
                    && interactCfg.IsHeroRotate)
                {
                    var moveComponent = playerAvatarEntity?.GetComponent<MainCityMoveComponent>(ETComponentType.EntityMove);
                    if (moveComponent != null)
                    {
                        await moveComponent.RotateWithAnimation(otherEntity.unityPosOfData);
                    }
                }
                await InteractWithNPC(interactCfg, otherEntity as MainCityNormalEntity);
            }
            _isInteractingWithNpc = false;
        }

        public async UniTask InteractWithNPC(CfgEntityInteractType interactCfg, MainCityNormalEntity interactEntity)
        {
            //保证交互不重复打开交互选项UI
            //如果交互选项UI不经过玩家选择而关闭时会取消Task，执行打开UI时await的后续逻辑，所以最好放在最前面
            //由于交互选项UI不能阻挡摇杆，而交互按钮和摇杆都在输入UI上，所以不能通过阻挡交互按钮来规避重复交互，必须加这行代码
            //交互逻辑涉及的UI只有交互选项UI，所以这里不去拆分输入UI，避免代码混乱
            ManagerCenter.UI.CloseWindow<UIInteractOption>();

            //查看身上有没有特殊功能，比如任务，商店，如果没有就直接发送交互请求，否则打开交互选项面板
            var entityConfig = interactEntity.dynNormalEntity.entityConfig;
            IReadOnlyList<int> quests = interactEntity.offeredQuests;
            IReadOnlyList<DialogReference> dialogs = null;
            if (entityConfig.paramMap.TryGetValue(MainCityEntityDynParamType.StoryDialog, out var dynParam))
            {
                dialogs = (dynParam as MainCityDynParamDialog).dialogs;
            }
            bool hasService = entityConfig.paramMap.ContainsKey(MainCityEntityDynParamType.Service);
            if (quests != null || dialogs != null)
            {
                var bsCom = interactEntity.GetComponent<EntityBehavScriptComponent>(ETComponentType.EntityBehavScript);
                bsCom?.Break();
                var moveCom = interactEntity.GetComponent<EntityMoveComponent>(ETComponentType.EntityMove);
                moveCom?.RotateWithAnimation(playerAvatarEntity.transform.position);
                var result = await GameScenePlayUtil.InteractWithEntity(quests, dialogs, interactCfg, interactEntity, hasService);
                switch (result.type)
                {
                    case EntityInteractOptionResultType.Quest://接任务
                        int selectedQuestCid = result.value;
                        var cfgQuest = TableCenter.quest.Get(selectedQuestCid);
                        if (cfgQuest.ReceiveStory != 0)
                        {
                            await StoryManager.Instance.StartPlayStoryById(cfgQuest.ReceiveStory, 0, interactEntity, true);
                        }
                        var netResult = await QuestModule.NetCore.CS_acceptQuest(selectedQuestCid);
                        if (netResult.IsFail)
                        {
                            LogGame.LogError($"接任务失败，服务器返回: {netResult.code}");
                        }
                        break;
                    case EntityInteractOptionResultType.StoryDialog:
                        int storyCid = result.value;
                        await StoryManager.Instance.StartPlayStoryById(storyCid, 0, interactEntity, true);
                        PlayerModule.NetCore.CS_uploadStoryCompleted(NetProtocol.Enum.GamePlayAreaType.MainCity, storyCid);
                        break;
                    case EntityInteractOptionResultType.Default: //默认交互
                        RequestDefaultInteract(interactEntity);
                        break;
                    case EntityInteractOptionResultType.Cancel:
                        LogGame.Log("取消选项");
                        break;
                    default: //非正常结束
                        break;
                }
                bsCom?.Continue();
            }
            else if (hasService)
            {
                //npc没有任务，商店等，发送交互请求，执行默认交互
                //直接交互需要按照交互配置来延迟发送请求，等待npc播放动作
                if (interactCfg.ActionID != 0 && interactCfg.Delay > 0)
                {
                    uint timerId = TimerManager.Instance.StartOneTimer((float)interactCfg.Delay / 1000);
                    await timerId.AwaitTimer();
                }
                RequestDefaultInteract(interactEntity);
            }
        }

        private void RequestDefaultInteract(MainCityNormalEntity interactEntity)
        {
#if UNITY_EDITOR
            LogGame.Log("主城默认交互，类型:" + _curInteracType.ToString());
#endif
            interactEntity.TryTriggerService(MainCityTriggerType.Interact, out var anyExecDone);
        }

        private async UniTask PlayInteractAnimation()
        {
            float duration;
            if (_curInteracType == 0)
            {
                playerAvatarEntity.GetComponent<MainCityAnimationComponent>(ETComponentType.EntityAnimation).PlayAttack();
                duration = 0.8f;
            }
            else
            {
                var interactCfg = TableCenter.entityInteractType.Get(_curInteracType);
                duration = (float)interactCfg.Delay / 1000;
                playerAvatarEntity.GetComponent<MainCityAnimationComponent>(ETComponentType.EntityAnimation).StartAnimAction(interactCfg.ActionID);
            }

            //等待
            _playInteractAnimTimerId = TimerManager.Instance.StartOneTimer(duration);
            await _playInteractAnimTimerId.AwaitTimer();
        }

        protected override void OnUpdate(float deltaTime)
        {
            if (!isActive)
            {
                return;
            }
            _checkInteractObjTimer += deltaTime;
            if (_checkInteractObjTimer >= ViewEntityConst.CheckInteractInterval)
            {
                _checkInteractObjTimer = 0;
                CalcInteractObject();
            }

            //设置交互按钮
            if (_curInteracType == 0)
            {
                this.uiInput?.SetInteractState(1);
            }
            else
            {
                this.uiInput?.SetInteractState(_curInteracType);
            }

            if (isMoving)
            {
                _syncMoveElapsedTime += deltaTime;
                _moveCheckElapsedTime += deltaTime;
                if (_syncMoveElapsedTime >= MainCityConst.MoveSyncInterval)
                {
                    SyncPlayerPosToServer();
                }
                if (_moveCheckElapsedTime >= MainCityConst.MoveCheckInterval)
                {
                    CheckMove();
                }
            }
        }

        private void SyncPlayerPosToServer()
        {
            var pos = playerAvatarEntity.transform.position;
            MainCityModule.NetCore.CS_uploadPlayerPos(regionCtrl.cfgRegion.Id, pos.x, pos.y, pos.z);
            _syncMoveElapsedTime = 0;
        }

        private void CheckMove()
        {
            regionCtrl.CheckMove(_playerAvatarEntity);
            _moveCheckElapsedTime = 0;
        }

        /// <summary>
        /// 计算哪个对象是交互对象
        /// </summary>
        private void CalcInteractObject()
        {
            var character = playerAvatarEntity;
            if (character == null)
            {
                return;
            }

            //从四叉树获取附近所有实体
            var qtEntitys = ListPool<MainCityBaseEntity>.Get();
            regionCtrl.entityCtrl.QTQueryObjects(qtEntitys, character.transform.position);

            // 当前交互类型
            int oldInteracType = _curInteracType;
            int oldInteractEntityId = _curInteractEntityId;

            _curInteracType = 0;

            //计算是否存在优先级最高的可交互实体
            MainCityNormalEntity interactEntity = null;
            float minPriority = float.MaxValue;
            foreach (var e in qtEntitys)
            {
                if (!(e is MainCityNormalEntity normalEntity))
                {
                    continue;
                }
                var entityInteractType = normalEntity.dynNormalEntity.entityConfig.interactType;
                if (entityInteractType == 0) //不能交互
                {
                    continue;
                }

                var characterForward = character.transform.forward;
                characterForward.y = 0;
                //计算优先级
                var priority = GameScenePlayUtil.GetEntityInteractPriority(character.cfgEntity.InteractExtendedRange,
                   character.unityPosOfData, characterForward, entityInteractType,
                   normalEntity.unityPosOfData, normalEntity.dynNormalEntity.entityConfig.obstacle);

                if (priority < minPriority)
                {
                    minPriority = priority;
                    interactEntity = normalEntity;
                }
            }

            bool changed = false;
            //当前有可以交互的实体
            if (interactEntity != null && !interactEntity.transform.isValueNull)
            {
                _curInteracType = interactEntity.dynNormalEntity.entityConfig.interactType;
                _curInteractEntityId = interactEntity.id;
                if (_curInteracType != oldInteracType || _curInteractEntityId != oldInteractEntityId)
                {
                    changed = true;
                }
            }
            else if (oldInteracType != 0)
            {
                changed = true;
                interactEntity = null;
            }

            if (changed)
            {
                // 更改之后,需要刷新头顶指示器
                RefreshInteactHeadIndicator(interactEntity);
            }

            ListPool<MainCityBaseEntity>.Put(qtEntitys);
        }

        /// <summary>
        /// 刷新头顶指示器
        /// </summary>
        /// <param name="interactEntity"></param>
        private void RefreshInteactHeadIndicator(MainCityNormalEntity interactEntity)
        {
            if (_curInteracType == 0 || interactEntity == null)
            {
                SetHeadIndicatorOn(false);
                return;
            }

            var dynEntity = interactEntity.dynNormalEntity;
            if (dynEntity.cfgEntity.NoInteractiveIcon)
            {
                SetHeadIndicatorOn(false);
                return;
            }

            // 显示头顶指示器
            SetHeadIndicatorOn(true, interactEntity);
            var constraintSource = headIndicator.GetSource(0);
            var bindPointCom = interactEntity.GetComponent<EntityBindPointComponent>(ETComponentType.EntityBindPoint);
            constraintSource.sourceTransform = bindPointCom.GetBindPoint(EntityBindPointCommonType.Top);
            headIndicator.SetSource(0, constraintSource);
        }

        private void SetHeadIndicatorOn(bool isActive, MainCityNormalEntity entity = null)
        {
            headIndicator.gameObject.SetActive(isActive);
            if (isActive)
            {
                if (indicateEntity != entity)
                {
                    indicateEntity?.OnIndicatorChange(false);
                    entity.OnIndicatorChange(true);
                    indicateEntity = entity;
                }
            }
            else
            {
                indicateEntity?.OnIndicatorChange(false);
                indicateEntity = null;
            }
        }

        protected override void OnDispose()
        {
            LeanTouch.OnGesture -= OnTouchGesture;
            LeanTouch.OnFingerTap -= OnTouchTap;
            LeanTouch.OnFingerUp -= OnTouchUp;
            onTouchTap = null;
            onTouchGesture = null;
            onTouchUp = null;
            if (headIndicator != null)
            {
                UnityEngine.Object.Destroy(headIndicator.gameObject);
            }
        }
    }
}
